package com.meisupic.copyright.configuration;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.AuthorizationScope;
import springfox.documentation.service.ClientCredentialsGrant;
import springfox.documentation.service.GrantType;
import springfox.documentation.service.OAuth;
import springfox.documentation.service.Parameter;
import springfox.documentation.service.ResourceOwnerPasswordCredentialsGrant;
import springfox.documentation.service.SecurityReference;
import springfox.documentation.service.SecurityScheme;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger.web.ApiKeyVehicle;
import springfox.documentation.swagger.web.SecurityConfiguration;

@Configuration
public class Swagger extends WebMvcConfigurerAdapter {

  @Value("${access_token_uri}")
  private String accessTokenUri;

  @Override
  public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("swagger-ui.html")
        .addResourceLocations("classpath:/META-INF/resources/");
    registry.addResourceHandler("/webjars/**")
        .addResourceLocations("classpath:/META-INF/resources/webjars/");
  }

  @Bean
  public Docket createRestApi() {
    return new Docket(DocumentationType.SWAGGER_2)
        .apiInfo(apiInfo()).globalOperationParameters(parameters())
        .select()
        .apis(RequestHandlerSelectors.basePackage("com.meisupic.copyright.api.controller"))
        .paths(PathSelectors.any())
        .build().securityContexts(Collections.singletonList(securityContext()))
        .securitySchemes(Arrays.asList(securitySchema()))
        .apiInfo(apiInfo());
  }

  private ApiInfo apiInfo() {
    return new ApiInfoBuilder()
        .title("花瓣美素开发文档")
        .description("接口使用方式\n 1 获取access_token。\n \t access_token是调用接口的全局唯一票据，"
            + "各接口调用时都需使用access_token。开发者需要进行妥善保存。access_token的有效期目前为2个小时，"
            + "需定时刷新。接口请求说明：http post请求 http://www.meisubq.com//oauth/token?"
            + "grant_type=client_credentials&client_id=852552747437932544&client_secret="
            + "ca1b8489d59e49db92d2f17be277e18(测试环境是用户自行替换响应的域名，client_id和client_secret"
            + "向相关人员索取)接口正常请求响应是会返回如下格式的数据{\"access_token\":"
            + "\"b9955878-667c-4a6d-8d93-7ea4c71b0725\",\"token_type\":\"bearer\","
            + "\"expires_in\":1140,\"scope\":\"all\"}。\n参数说明：access_token\t获取到的凭证"
            + "expires_in\t凭证有效时间，单位：秒\n"
            + "2 获取到access_token后可通过以下两种方式请求接口。1、在request header中加上Authorization:"
            + " Basic access_token。2、所有request url加上参数access_token。示例"
            + "http://localhost:9090/api/copyright/save?access_token= \n"
            + "3 实名认证回调接口：当第三方系统用户的证件图片不能正常下载时，系统会异步回调第三方提供的回调"
            + "接口，回调参数数据格式在Models中有说明（RealnameCallBackParamsVo）,http 请求"
            + "方式为post请求，Content-Type为application/json \n"
            + "4 版权登记回调接口：当第三方系统用户的登记作品审核完成时（通过或拒绝），系统会回调"
            + "第三方系统接口，将审核结果推送至第三方系统。回调参数见下面Models中（RegisterCallBackParamsVo）,http 请求\"\n"
            + "            + \"方式为post请求，Content-Type为application/json。当登记系统回调第三方接口失败时，"
            + "会定时重试5次。当第三方系统一直无法获取到作品状态信息 ，可调用查询接口查询状态 \n")
        .version("1.0")
        .build();
  }

  private List<Parameter> parameters() {
    ParameterBuilder aParameterBuilder = new ParameterBuilder();
    aParameterBuilder.parameterType("header").name("Authorization").defaultValue("")
        .description("${token}").modelRef(new ModelRef("string"))
        .required(false).build();
    List<Parameter> aParameters = new ArrayList<>();
    aParameters.add(aParameterBuilder.build());
    return aParameters;
  }


  private OAuth securitySchema() {

    List<AuthorizationScope> authorizationScopeList = new ArrayList();
    authorizationScopeList.add(new AuthorizationScope("read", "read all"));
    authorizationScopeList.add(new AuthorizationScope("write", "access all"));

    List<GrantType> grantTypes = new ArrayList();
    GrantType clientCredentialsGrant = new ClientCredentialsGrant(accessTokenUri);
    grantTypes.add(clientCredentialsGrant);

    return new OAuth("oauth2", authorizationScopeList, grantTypes);
  }

  private SecurityContext securityContext() {
    return SecurityContext.builder().securityReferences(defaultAuth())
        .build();

  }

  private List<SecurityReference> defaultAuth() {

    final AuthorizationScope[] authorizationScopes = new AuthorizationScope[3];
    authorizationScopes[0] = new AuthorizationScope("read", "read all");
    authorizationScopes[1] = new AuthorizationScope("trust", "trust all");
    authorizationScopes[2] = new AuthorizationScope("write", "write all");

    return Collections.singletonList(new SecurityReference("oauth2", authorizationScopes));
  }


}
